import { openDB, type IDBPDatabase } from 'idb';

// 泛型 T 用于控制数据类型
export class IndexedDBHelper<T> {
    public dbName: string;
    public storeName: string;
    public dbVersion: number;

    constructor(dbName: string, storeName: string) {
        this.dbName = dbName;
        this.storeName = storeName;
        this.dbVersion = 1;
    }

    // 生成随机字符串 guid
    private generateGUID(): string {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    // 打开数据库并创建 stores（如果需要）
    private async openDatabase(): Promise<IDBPDatabase> {
        return openDB(this.dbName, this.dbVersion, {
            upgrade: (db) => {
                if (!db.objectStoreNames.contains(this.storeName)) {
                    db.createObjectStore(this.storeName, { keyPath: 'id' });
                }
            },
        });
    }

    // 删除一周以前的数据
    private async deleteOldData(): Promise<void> {
        const db = await this.openDatabase();
        const tx = db.transaction(this.storeName, 'readwrite');
        const store = tx.objectStore(this.storeName);

        const oneWeekAgo = new Date().getTime() - 7 * 24 * 60 * 60 * 1000; // 一周前的时间戳

        let cursor = await store.openCursor();
        while (cursor) {
            const data = cursor.value;
            // 如果数据的 `creatDateTime` 小于一周前，删除该数据
            if (data.creatDateTime && data.creatDateTime < oneWeekAgo) {
                await cursor.delete();
            }
            cursor = await cursor.continue();
        }
        await tx.done;
    }

    // 添加数据并删除一周以前的数据
    async addData(data: T): Promise<void> {
        const db = await this.openDatabase();

        // 删除一周以前的数据
        await this.deleteOldData();

        // 生成一个随机字符串作为键
        const randomKey = this.generateGUID();
        await db.add(this.storeName, { ...data, id: randomKey, creatDateTime: new Date().getTime() });
    }

    // 更新数据
    async updateData(data: T): Promise<void> {
        const db = await this.openDatabase();
        await db.put(this.storeName, data);
    }

    // 读取数据
    async getData(id: string): Promise<T | undefined> {
        const db = await this.openDatabase();
        return db.get(this.storeName, id);
    }

    // 删除数据
    async deleteData(id: string): Promise<void> {
        const db = await this.openDatabase();
        await db.delete(this.storeName, id);
    }

    // 读取所有数据
    async getAllData(): Promise<T[]> {
        const db = await this.openDatabase();
        return db.getAll(this.storeName);
    }

    // 分页读取数据
    async getDataByPage(page: number, pageSize: number): Promise<T[]> {
        const db = await this.openDatabase();
        const tx = db.transaction(this.storeName, 'readonly');
        const store = tx.objectStore(this.storeName);
        const result: T[] = [];
        let cursor = await store.openCursor();
        let skipped = 0;
        let fetched = 0;

        // 计算跳过的记录数
        const skip = (page - 1) * pageSize;

        // 遍历 cursor 并实现分页
        while (cursor) {
            if (skipped < skip) {
                skipped++;
            } else if (fetched < pageSize) {
                result.push(cursor.value as T);
                fetched++;
            } else {
                break;
            }
            cursor = await cursor.continue();
        }

        return result;
    }
}
